home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
QRZ! Ham Radio 6
/
QRZ Ham Radio Callsign Database - Volume 6.iso
/
mac
/
files
/
amiga
/
csrc720j.lzh
/
lock.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-01-18
|
7KB
|
248 lines
/* lock.c Handles the semaphore locking interface
Copyright Feb. 1991, Peter Hardie VE5VA.
The setbusy/clrbusy/getbusy/unbusy calls are used to protect the 'GM'
and 'GU' commands so that only the sysop process running the 'GM'
can be executing at the time that the 'GM' or 'GU' proceeds.
Each process executes setbusy() when it is active and clrbusy when
it is going to sleep again (in do_idle usually). A process that
wants to do a 'GM' or 'GU' must first do a getbusy() which will either
return a value of 1 to indicate failure or otherwise it is safe to
proceed. When it has finished it must execute unbusy().
This is equivalent to the classic case of the "multiple reader -
single writer" problem.
The begin_lock and end_lock calls are simple semaphores used to protect
write calls into the files, mail.dat, bid.mb, and user.dat. They also
protect the calls to generate the WP message and also the call to the
stale() routine. In fmsg() they lock the message currently being
forwarded.
Ideally, the locks for each file could be different which would allow
one user writing in the mail file to proceed even if another is causing
a write into the bid file (for example). I may get around to creating a
semaphore for each file once this code settles down a bit!
*/
#include <exec/types.h>
#include <exec/exec.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "lock.h"
extern int debug;
/*
struct Message *lock_msg;
struct MsgPort *sema_lock;
*/
struct Message *busy_msg,*mail_msg,*user_msg,*bid_msg;
struct user_sem *sema_busy; /* Implementation of busy is a bit different
than for lock. user_sem is a semaphore and
a process counter.
*/
struct file_sem *sema_mail = 0L,*sema_user = 0L, *sema_bid = 0L;
/* Set up both semaphores */
findlock()
{
/* set up and find the semaphores for begin_lock and end_lock.
This does not need to look for the locker process as that has
already been done and we are guaranteed that it exists.
*/
/*
lock_msg = AllocMem(sizeof(*lock_msg), MEMF_CLEAR | MEMF_PUBLIC);
if(lock_msg == 0)return(1);
lock_msg->mn_ReplyPort = CreatePort(0L,0L);
sema_lock = FindPort(SEM_LOCK);
if(sema_lock == 0) {
stoplock();
return(1);
}
*/
/* set up and find the semaphore for set/clr/get/unbusy */
busy_msg = AllocMem(sizeof(*busy_msg), MEMF_CLEAR | MEMF_PUBLIC);
if(busy_msg == 0)return(1);
busy_msg->mn_ReplyPort = CreatePort(0L,0L);
sema_busy = (struct user_sem *) FindPort(SEM_BUSY);
if(sema_busy == 0) {
stoplock();
return(2);
}
/* Create the mail.dat semaphore */
mail_msg = AllocMem(sizeof(*mail_msg), MEMF_CLEAR | MEMF_PUBLIC);
if(mail_msg == 0)return(1);
mail_msg->mn_ReplyPort = CreatePort(0L,0L);
sema_mail = (struct file_sem *) FindPort(SEM_MAIL);
if(sema_mail == 0) {
stoplock();
return(3);
}
/* Create the user.dat semaphore */
user_msg = AllocMem(sizeof(*user_msg), MEMF_CLEAR | MEMF_PUBLIC);
if(user_msg == 0)return(1);
user_msg->mn_ReplyPort = CreatePort(0L,0L);
sema_user = (struct file_sem *) FindPort(SEM_USER);
if(sema_user == 0) {
stoplock();
return(4);
}
/* Create the bid.mb semaphore */
bid_msg = AllocMem(sizeof(*bid_msg), MEMF_CLEAR | MEMF_PUBLIC);
if(bid_msg == 0)return(1);
bid_msg->mn_ReplyPort = CreatePort(0L,0L);
sema_bid = (struct file_sem *) FindPort(SEM_BID);
if(sema_bid == 0) {
stoplock();
return(5);
}
return(0);
}
stoplock()
{
/*
if(lock_msg) {
if(lock_msg->mn_ReplyPort)DeletePort(lock_msg->mn_ReplyPort);
FreeMem(lock_msg,sizeof(*lock_msg));
}
*/
if(busy_msg) {
if(busy_msg->mn_ReplyPort)DeletePort(busy_msg->mn_ReplyPort);
FreeMem(busy_msg,sizeof(*busy_msg));
}
if(mail_msg) {
if(mail_msg->mn_ReplyPort)DeletePort(mail_msg->mn_ReplyPort);
FreeMem(mail_msg,sizeof(*mail_msg));
}
if(user_msg) {
if(user_msg->mn_ReplyPort)DeletePort(user_msg->mn_ReplyPort);
FreeMem(user_msg,sizeof(*user_msg));
}
if(bid_msg) {
if(bid_msg->mn_ReplyPort)DeletePort(bid_msg->mn_ReplyPort);
FreeMem(bid_msg,sizeof(*bid_msg));
}
}
/* begin_lock and end_lock are not used in the multi-user CBBS any more
so make them dummy routines
*/
begin_lock()
{
/*
if(Procure((struct Semaphore *)sema_lock,lock_msg) == 0) {
WaitPort(lock_msg->mn_ReplyPort);
GetMsg(lock_msg->mn_ReplyPort);
}
*/
}
end_lock()
{
/*
Vacate((struct Semaphore *)sema_lock);
*/
}
setbusy()
{
if(Procure((struct Semaphore *)sema_busy,busy_msg) == 0) {
WaitPort(busy_msg->mn_ReplyPort);
GetMsg(busy_msg->mn_ReplyPort);
}
sema_busy->count++;
Vacate((struct Semaphore *)sema_busy);
}
clrbusy()
{
if(Procure((struct Semaphore *)sema_busy,busy_msg) == 0) {
WaitPort(busy_msg->mn_ReplyPort);
GetMsg(busy_msg->mn_ReplyPort);
}
sema_busy->count--;
Vacate((struct Semaphore *)sema_busy);
}
/* This returns 1 if there's more than one user active (itself).
The setbusy/clrbusy/getbusy/unbusy are used only to lock out users
while either a 'GM' or 'GU' are being done.
*/
getbusy()
{
if(Procure((struct Semaphore *)sema_busy,busy_msg) == 0) {
WaitPort(busy_msg->mn_ReplyPort);
GetMsg(busy_msg->mn_ReplyPort);
}
/* NOTE here that if the count is one, then we return success and
do NOT Vacate the semaphore. The process MUST call unbusy() at
a later time to clear the semaphore
*/
if(sema_busy->count == 1) {
return(0);
}
/* The count is wrong so just Vacate the semaphore and return failure
*/
Vacate((struct Semaphore *)sema_busy);
return(1);
}
unbusy()
{
Vacate((struct Semaphore *)sema_busy);
}
lock_bid()
{
if(Procure((struct Semaphore *)sema_bid,bid_msg) == 0) {
WaitPort(bid_msg->mn_ReplyPort);
GetMsg(bid_msg->mn_ReplyPort);
}
}
unlock_bid()
{
Vacate((struct Semaphore *)sema_bid);
}
lock_user()
{
if(Procure((struct Semaphore *)sema_user,user_msg) == 0) {
WaitPort(user_msg->mn_ReplyPort);
GetMsg(user_msg->mn_ReplyPort);
}
}
unlock_user()
{
Vacate((struct Semaphore *)sema_user);
}
/* Process must have the semaphore already to do these next two */
set_user(i)
long i;
{
sema_user->filesize = i;
}
long get_user()
{
return(sema_user->filesize);
}
lock_mail()
{
if(Procure((struct Semaphore *)sema_mail,mail_msg) == 0) {
WaitPort(mail_msg->mn_ReplyPort);
GetMsg(mail_msg->mn_ReplyPort);
}
}
unlock_mail()
{
Vacate((struct Semaphore *)sema_mail);
}
set_mail(i)
long i;
{
sema_mail->filesize = i;
}
long get_mail()
{
return(sema_mail->filesize);
}